#!/usr/bin/env python
# -*- encoding: utf-8 -*-

# Required interfaces:
# DirectShow:
#   ICaptureGraphBuilder2 -> SetFilterGraph(qedit.IGraphBuilder)
#   ICreateDevEnum -> CreateClassEnumerator(GUID * clsidDeviceClass)
#       \-> IEnumMoniker -> RemoteNext(int) | Reset()
#           \-> IMoniker(IPersistStream(IPersist)) -> RemoteBindToObject
#             -> IUnknown.
#   IBaseFilter(IMediaFilter) -> AddFilter() | ConnectDirect()
# EnhancedVideoRenderer/MediaFoundation:
#   IMFGetService
#   IMFVideoDisplayControl

from comtypes import GUID, COMMETHOD, tagBIND_OPTS2, wireHWND
from comtypes import IUnknown, IPersist, CoClass
from comtypes.typeinfo import ULONG_PTR
from ctypes import *
from ctypes.wintypes import _LARGE_INTEGER, _ULARGE_INTEGER, _FILETIME, \
    tagSIZE, tagRECT

WSTRING = c_wchar_p
LONG_PTR = c_int
OAFALSE = 0
OATRUE = -1

(PhysConn_Video_Tuner, 
PhysConn_Video_Composite,
PhysConn_Video_SVideo,
PhysConn_Video_RGB,
PhysConn_Video_YRYBY,
PhysConn_Video_SerialDigital,
PhysConn_Video_ParallelDigital,
PhysConn_Video_SCSI,
PhysConn_Video_AUX,
PhysConn_Video_1394,
PhysConn_Video_USB,
PhysConn_Video_VideoDecoder,
PhysConn_Video_VideoEncoder,
PhysConn_Video_SCART,
PhysConn_Video_Black) = tuple(range(1,16))


(PhysConn_Audio_Tuner,
PhysConn_Audio_Line,
PhysConn_Audio_Mic,
PhysConn_Audio_AESDigital,
PhysConn_Audio_SPDIFDigital,
PhysConn_Audio_SCSI,
PhysConn_Audio_AUX,
PhysConn_Audio_1394,
PhysConn_Audio_USB,
PhysConn_Audio_AudioDecoder) = tuple(range(4096,4106))

AnalogVideo_None = 0
AnalogVideo_NTSC_M = 1
AnalogVideo_NTSC_M_J = 2
AnalogVideo_NTSC_433 = 4
AnalogVideo_PAL_B = 16
AnalogVideo_PAL_D = 32
AnalogVideo_PAL_G = 64
AnalogVideo_PAL_H = 128
AnalogVideo_PAL_I = 256
AnalogVideo_PAL_M = 512
AnalogVideo_PAL_N = 1024
AnalogVideo_PAL_60 = 2048
AnalogVideo_SECAM_B = 4096
AnalogVideo_SECAM_D = 8192
AnalogVideo_SECAM_G = 16384
AnalogVideo_SECAM_H = 32768
AnalogVideo_SECAM_K = 65536
AnalogVideo_SECAM_K1 = 131072
AnalogVideo_SECAM_L = 262144
AnalogVideo_SECAM_L1 = 524288
AnalogVideo_PAL_N_COMBO = 1048576

MFVideoARMode_PreservePicture = 0x1

####
## Forward declarations
class IReferenceClock(IUnknown):
    _case_insensitive_ = True
    _iid_ = GUID('{56A86897-0AD4-11CE-B03A-0020AF0BA770}')
    _idlflags_ = []
class IMediaFilter(IPersist):
    _case_insensitive_ = True
    _iid_ = GUID('{56A86899-0AD4-11CE-B03A-0020AF0BA770}')
    _idlflags_ = []
class IBaseFilter(IMediaFilter):
    _case_insensitive_ = True
    _iid_ = GUID('{56A86895-0AD4-11CE-B03A-0020AF0BA770}')
    _idlflags_ = []
class IPin(IUnknown):
    _case_insensitive_ = True
    _iid_ = GUID('{56A86891-0AD4-11CE-B03A-0020AF0BA770}')
    _idlflags_ = []
class IFilterGraph(IUnknown):
    _case_insensitive_ = True
    _iid_ = GUID('{56A8689F-0AD4-11CE-B03A-0020AF0BA770}')
    _idlflags_ = []
class IGraphBuilder(IFilterGraph):
    _case_insensitive_ = True
    _iid_ = GUID('{56A868A9-0AD4-11CE-B03A-0020AF0BA770}')
    _idlflags_ = []
class FilterGraph(CoClass):
    _reg_clsid_ = GUID('{E436EBB3-524F-11CE-9F53-0020AF0BA770}')
    _idlflags_ = []
    _reg_typelib_ = ('{24BC6711-3881-420F-8299-34DA1026D31E}', 1, 0)
    _com_interfaces_ = [IGraphBuilder, IFilterGraph]
class ICaptureGraphBuilder2(IUnknown):
    _case_insensitive_ = True
    _iid_ = GUID('{93E5A4E0-2D50-11D2-ABFA-00A0C9C6E38D}')
    _idlflags_ = []
class CaptureGraphBuilder2(CoClass):
    _reg_clsid_ = GUID('{BF87B6E1-8C27-11D0-B3F0-00AA003761C5}')
    _idlflags_ = []
    _reg_typelib_ = ('{24BC6711-3881-420F-8299-34DA1026D31E}', 1, 0)
    _com_interfaces_ = [ICaptureGraphBuilder2]
class IFileSinkFilter(IUnknown):
    _case_insensitive_ = True
    _iid_ = GUID('{A2104830-7C70-11CF-8BCE-00AA00A3F1A6}')
    _idlflags_ = []
class IAMCopyCaptureFileProgress(IUnknown):
    _case_insensitive_ = True
    _iid_ = GUID('{670D1D20-A068-11D0-B3F0-00AA003761C5}')
    _idlflags_ = []
class IPersistStream(IPersist):
    _case_insensitive_ = True
    _iid_ = GUID('{00000109-0000-0000-C000-000000000046}')
    _idlflags_ = []
class IMoniker(IPersistStream):
    _case_insensitive_ = True
    _iid_ = GUID('{0000000F-0000-0000-C000-000000000046}')
    _idlflags_ = []
class ISequentialStream(IUnknown):
    _case_insensitive_ = True
    _iid_ = GUID('{0C733A30-2A1C-11CE-ADE5-00AA0044773D}')
    _idlflags_ = []
class IStream(ISequentialStream):
    _case_insensitive_ = True
    _iid_ = GUID('{0000000C-0000-0000-C000-000000000046}')
    _idlflags_ = []
class IBindCtx(IUnknown):
    _case_insensitive_ = True
    _iid_ = GUID('{0000000E-0000-0000-C000-000000000046}')
    _idlflags_ = []
class IEnumMoniker(IUnknown):
    _case_insensitive_ = True
    _iid_ = GUID('{00000102-0000-0000-C000-000000000046}')
    _idlflags_ = []
class IRunningObjectTable(IUnknown):
    _case_insensitive_ = True
    _iid_ = GUID('{00000010-0000-0000-C000-000000000046}')
    _idlflags_ = []
class IEnumString(IUnknown):
    _case_insensitive_ = True
    _iid_ = GUID('{00000101-0000-0000-C000-000000000046}')
    _idlflags_ = []
class ICreateDevEnum(IUnknown):
    _case_insensitive_ = True
    _iid_ = GUID('{29840822-5B84-11D0-BD3B-00A0C911CE86}')
    _idlflags_ = []
class IMFGetService(IUnknown):
    _case_insensitive_ = True
    _iid_ = GUID('{FA993888-4383-415A-A930-DD472A8CF6F7}')
    _idlflags_ = []
class IMFVideoDisplayControl(IUnknown):
    _case_insensitive_ = True
    'IMFVideoDisplayControl Interface'
    _iid_ = GUID('{A490B1E4-AB84-4D31-A1B2-181E03B1077A}')
    _idlflags_ = []
class IAMCrossbar(IUnknown):
    _case_insensitive_ = True
    _iid_ = GUID('{C6E13380-30AC-11D0-A18C-00A0C9118956}')
    _idlflags_ = []
class IAMAnalogVideoDecoder(IUnknown):
    _case_insensitive_ = True
    _iid_ = GUID('{C6E13350-30AC-11D0-A18C-00A0C9118956}')
    _idlflags_ = []

####
## Forward decl of enumerators:
class IEnumMediaTypes(IUnknown):
    _case_insensitive_ = True
    _iid_ = GUID('{89C31040-846B-11CE-97D3-00AA0055595A}')
    _idlflags_ = []
    def __iter__(self):
        return self

    def next(self):
        item, fetched = self.Next(1)
        if fetched:
            return item
        raise StopIteration

    def __getitem__(self, index):
        self.Reset()
        self.Skip(index)
        item, fetched = self.Next(1)
        if fetched:
            return item
        raise IndexError(index)
class IEnumPins(IUnknown):
    _case_insensitive_ = True
    _iid_ = GUID('{56A86892-0AD4-11CE-B03A-0020AF0BA770}')
    _idlflags_ = []
    def __iter__(self):
        return self

    def next(self):
        item, fetched = self.Next(1)
        if fetched:
            return item
        raise StopIteration

    def __getitem__(self, index):
        self.Reset()
        self.Skip(index)
        item, fetched = self.Next(1)
        if fetched:
            return item
        raise IndexError(index)
class IEnumFilters(IUnknown):
    _case_insensitive_ = True
    _iid_ = GUID('{56A86893-0AD4-11CE-B03A-0020AF0BA770}')
    _idlflags_ = []
    def __iter__(self):
        return self

    def next(self):
        item, fetched = self.Next(1)
        if fetched:
            return item
        raise StopIteration

    def __getitem__(self, index):
        self.Reset()
        self.Skip(index)
        item, fetched = self.Next(1)
        if fetched:
            return item
        raise IndexError(index)

####
## Structures and Enums
PINDIR_INPUT = 0
PINDIR_OUTPUT = 1
_PinDirection = c_int # enum

State_Stopped = 0
State_Paused = 1
State_Running = 2
_FilterState = c_int # enum

class MFVideoNormalizedRect(Structure):
    _fields_ = [
        ('left', c_float),
        ('top', c_float),
        ('right', c_float),
        ('bottom', c_float),
    ]
class BITMAPINFOHEADER(Structure):
    _fields_ = [
        ('biSize', c_ulong),
        ('biWidth', c_int),
        ('biHeight', c_int),
        ('biPlanes', c_ushort),
        ('biBitCount', c_ushort),
        ('biCompression', c_ulong),
        ('biSizeImage', c_ulong),
        ('biXPelsPerMeter', c_int),
        ('biYPelsPerMeter', c_int),
        ('biClrUsed', c_ulong),
        ('biClrImportant', c_ulong),
    ]
assert sizeof(BITMAPINFOHEADER) == 40, sizeof(BITMAPINFOHEADER)
assert alignment(BITMAPINFOHEADER) == 4, alignment(BITMAPINFOHEADER)

class _FilterInfo(Structure):
    _fields_ = [
        ('achName', c_ushort * 128),
        ('pGraph', POINTER(IFilterGraph)),
    ]
assert sizeof(_FilterInfo) == 264, sizeof(_FilterInfo)
assert alignment(_FilterInfo) == 8, alignment(_FilterInfo)
class _AMMediaType(Structure):
    _fields_ = [
        ('majortype', GUID),
        ('subtype', GUID),
        ('bFixedSizeSamples', c_int),
        ('bTemporalCompression', c_int),
        ('lSampleSize', c_ulong),
        ('formattype', GUID),
        ('punk', POINTER(IUnknown)),
        ('cbFormat', c_ulong),
        ('pbFormat', POINTER(c_ubyte)),
    ]
assert sizeof(_AMMediaType) == 88, sizeof(_AMMediaType)
assert alignment(_AMMediaType) == 8, alignment(_AMMediaType)
class _PinInfo(Structure):
    _fields_ = [
        ('pFilter', POINTER(IBaseFilter)),
        ('dir', _PinDirection),
        ('achName', c_ushort * 128),
    ]
assert sizeof(_PinInfo) == 272, sizeof(_PinInfo)
assert alignment(_PinInfo) == 8, alignment(_PinInfo)
class tagSTATSTG(Structure):
    _fields_ = [
        ('pwcsName', WSTRING),
        ('type', c_ulong),
        ('cbSize', _ULARGE_INTEGER),
        ('mtime', _FILETIME),
        ('ctime', _FILETIME),
        ('atime', _FILETIME),
        ('grfMode', c_ulong),
        ('grfLocksSupported', c_ulong),
        ('clsid', GUID),
        ('grfStateBits', c_ulong),
        ('reserved', c_ulong),
    ]
assert sizeof(tagSTATSTG) == 80, sizeof(tagSTATSTG)
assert alignment(tagSTATSTG) == 8, alignment(tagSTATSTG)
####
## Interface Methods

IMFGetService._methods_ = [
    COMMETHOD([], HRESULT, 'GetService',
              ( ['in'], POINTER(GUID), 'guidService' ),
              ( ['in'], POINTER(GUID), 'riid' ),
              ( ['out'], POINTER(POINTER(IUnknown)), 'ppvObject' )),
              #( ['out'], POINTER(c_void_p), 'ppvObject' )),
]

IMFVideoDisplayControl._methods_ = [
    COMMETHOD([], HRESULT, 'GetNativeVideoSize',
              ( ['in', 'out'], POINTER(tagSIZE), 'pszVideo' ),
              ( ['in', 'out'], POINTER(tagSIZE), 'pszARVideo' )),
    COMMETHOD([], HRESULT, 'GetIdealVideoSize',
              ( ['in', 'out'], POINTER(tagSIZE), 'pszMin' ),
              ( ['in', 'out'], POINTER(tagSIZE), 'pszMax' )),
    COMMETHOD([], HRESULT, 'SetVideoPosition',
              ( ['in'], POINTER(MFVideoNormalizedRect), 'pnrcSource' ),
              ( ['in'], POINTER(tagRECT), 'prcDest' )),
    COMMETHOD([], HRESULT, 'GetVideoPosition',
              ( ['out'], POINTER(MFVideoNormalizedRect), 'pnrcSource' ),
              ( ['out'], POINTER(tagRECT), 'prcDest' )),
    COMMETHOD([], HRESULT, 'SetAspectRatioMode',
              ( ['in'], c_ulong, 'dwAspectRatioMode' )),
    COMMETHOD([], HRESULT, 'GetAspectRatioMode',
              ( ['out'], POINTER(c_ulong), 'pdwAspectRatioMode' )),
    COMMETHOD([], HRESULT, 'SetVideoWindow',
              ( ['in'], wireHWND, 'hwndVideo' )),
    COMMETHOD([], HRESULT, 'GetVideoWindow',
              ( ['out'], POINTER(wireHWND), 'phwndVideo' )),
    COMMETHOD([], HRESULT, 'RepaintVideo'),
    COMMETHOD([], HRESULT, 'GetCurrentImage',
              ( ['in', 'out'], POINTER(BITMAPINFOHEADER), 'pBih' ),
              ( ['out'], POINTER(POINTER(c_ubyte)), 'pDib' ),
              ( ['out'], POINTER(c_ulong), 'pcbDib' ),
              ( ['in', 'out'], POINTER(c_longlong), 'pTimeStamp' )),
    COMMETHOD([], HRESULT, 'SetBorderColor',
              ( ['in'], c_ulong, 'Clr' )),
    COMMETHOD([], HRESULT, 'GetBorderColor',
              ( ['out'], POINTER(c_ulong), 'pClr' )),
    COMMETHOD([], HRESULT, 'SetRenderingPrefs',
              ( ['in'], c_ulong, 'dwRenderFlags' )),
    COMMETHOD([], HRESULT, 'GetRenderingPrefs',
              ( ['out'], POINTER(c_ulong), 'pdwRenderFlags' )),
    COMMETHOD([], HRESULT, 'SetFullscreen',
              ( ['in'], c_int, 'fFullscreen' )),
    COMMETHOD([], HRESULT, 'GetFullscreen',
              ( ['out'], POINTER(c_int), 'pfFullscreen' )),
]

IReferenceClock._methods_ = [
    COMMETHOD([], HRESULT, 'GetTime',
              ( ['out'], POINTER(c_longlong), 'pTime' )),
    COMMETHOD([], HRESULT, 'AdviseTime',
              ( ['in'], c_longlong, 'baseTime' ),
              ( ['in'], c_longlong, 'streamTime' ),
              ( ['in'], ULONG_PTR, 'hEvent' ),
              ( ['out'], POINTER(ULONG_PTR), 'pdwAdviseCookie' )),
    COMMETHOD([], HRESULT, 'AdvisePeriodic',
              ( ['in'], c_longlong, 'startTime' ),
              ( ['in'], c_longlong, 'periodTime' ),
              ( ['in'], ULONG_PTR, 'hSemaphore' ),
              ( ['out'], POINTER(ULONG_PTR), 'pdwAdviseCookie' )),
    COMMETHOD([], HRESULT, 'Unadvise',
              ( ['in'], ULONG_PTR, 'dwAdviseCookie' )),
]

IAMCopyCaptureFileProgress._methods_ = [
    COMMETHOD([], HRESULT, 'Progress',
              ( ['in'], c_int, 'iProgress' )),
]

ISequentialStream._methods_ = [
    COMMETHOD([], HRESULT, 'RemoteRead',
              ( ['out'], POINTER(c_ubyte), 'pv' ),
              ( ['in'], c_ulong, 'cb' ),
              ( ['out'], POINTER(c_ulong), 'pcbRead' )),
    COMMETHOD([], HRESULT, 'RemoteWrite',
              ( ['in'], POINTER(c_ubyte), 'pv' ),
              ( ['in'], c_ulong, 'cb' ),
              ( ['out'], POINTER(c_ulong), 'pcbWritten' )),
]

IMediaFilter._methods_ = [
    COMMETHOD([], HRESULT, 'Stop'),
    COMMETHOD([], HRESULT, 'Pause'),
    COMMETHOD([], HRESULT, 'Run',
              ( [], c_longlong, 'tStart' )),
    COMMETHOD([], HRESULT, 'GetState',
              ( ['in'], c_ulong, 'dwMilliSecsTimeout' ),
              ( ['out'], POINTER(_FilterState), 'State' )),
    COMMETHOD([], HRESULT, 'SetSyncSource',
              ( ['in'], POINTER(IReferenceClock), 'pClock' )),
    COMMETHOD([], HRESULT, 'GetSyncSource',
              ( ['out'], POINTER(POINTER(IReferenceClock)), 'pClock' )),
]

IEnumMediaTypes._methods_ = [
    COMMETHOD([], HRESULT, 'Next',
              ( ['in'], c_ulong, 'cMediaTypes' ),
              ( ['out'], POINTER(POINTER(_AMMediaType)), 'ppMediaTypes' ),
              ( ['out'], POINTER(c_ulong), 'pcFetched' )),
    COMMETHOD([], HRESULT, 'Skip',
              ( ['in'], c_ulong, 'cMediaTypes' )),
    COMMETHOD([], HRESULT, 'Reset'),
    COMMETHOD([], HRESULT, 'Clone',
              ( ['out'], POINTER(POINTER(IEnumMediaTypes)), 'ppenum' )),
]

IEnumFilters._methods_ = [
    COMMETHOD([], HRESULT, 'Next',
              ( ['in'], c_ulong, 'cFilters' ),
              ( ['out'], POINTER(POINTER(IBaseFilter)), 'ppFilter' ),
              ( ['out'], POINTER(c_ulong), 'pcFetched' )),
    COMMETHOD([], HRESULT, 'Skip',
              ( ['in'], c_ulong, 'cFilters' )),
    COMMETHOD([], HRESULT, 'Reset'),
    COMMETHOD([], HRESULT, 'Clone',
              ( ['out'], POINTER(POINTER(IEnumFilters)), 'ppenum' )),
]

IBaseFilter._methods_ = [
    COMMETHOD([], HRESULT, 'EnumPins',
              ( ['retval', 'out'], POINTER(POINTER(IEnumPins)), 'ppenum' )),
    COMMETHOD([], HRESULT, 'FindPin',
              ( ['in'], WSTRING, 'Id' ),
              ( ['retval', 'out'], POINTER(POINTER(IPin)), 'ppPin' )),
    COMMETHOD([], HRESULT, 'QueryFilterInfo',
              ( ['retval', 'out'], POINTER(_FilterInfo), 'pInfo' )),
    COMMETHOD([], HRESULT, 'JoinFilterGraph',
              ( ['in'], POINTER(IFilterGraph), 'pGraph' ),
              ( ['in'], WSTRING, 'pName' )),
    COMMETHOD([], HRESULT, 'QueryVendorInfo',
              ( ['retval', 'out'], POINTER(WSTRING), 'pVendorInfo' )),
]

IFilterGraph._methods_ = [
    COMMETHOD([], HRESULT, 'AddFilter',
              ( ['in'], POINTER(IBaseFilter), 'pFilter' ),
              ( ['in'], WSTRING, 'pName' )),
    COMMETHOD([], HRESULT, 'RemoveFilter',
              ( ['in'], POINTER(IBaseFilter), 'pFilter' )),
    COMMETHOD([], HRESULT, 'EnumFilters',
              ( ['out'], POINTER(POINTER(IEnumFilters)), 'ppenum' )),
    COMMETHOD([], HRESULT, 'FindFilterByName',
              ( ['in'], WSTRING, 'pName' ),
              ( ['out'], POINTER(POINTER(IBaseFilter)), 'ppFilter' )),
    COMMETHOD([], HRESULT, 'ConnectDirect',
              ( ['in'], POINTER(IPin), 'ppinOut' ),
              ( ['in'], POINTER(IPin), 'ppinIn' ),
              ( ['in'], POINTER(_AMMediaType), 'pmt' )),
    COMMETHOD([], HRESULT, 'Reconnect',
              ( ['in'], POINTER(IPin), 'pPin' )),
    COMMETHOD([], HRESULT, 'Disconnect',
              ( ['in'], POINTER(IPin), 'pPin' )),
    COMMETHOD([], HRESULT, 'SetDefaultSyncSource'),
]

IPin._methods_ = [
    COMMETHOD([], HRESULT, 'Connect',
              ( ['in'], POINTER(IPin), 'pReceivePin' ),
              ( ['in'], c_ulong, 'pmt' )),
    COMMETHOD([], HRESULT, 'ReceiveConnection',
              ( ['in'], POINTER(IPin), 'pConnector' ),
              ( ['in'], POINTER(_AMMediaType), 'pmt' )),
    COMMETHOD([], HRESULT, 'Disconnect'),
    COMMETHOD([], HRESULT, 'ConnectedTo',
              ( ['retval', 'out'], POINTER(POINTER(IPin)), 'pPin' )),
    COMMETHOD([], HRESULT, 'ConnectionMediaType',
              ( ['out'], POINTER(_AMMediaType), 'pmt' )),
    COMMETHOD([], HRESULT, 'QueryPinInfo',
              ( ['retval', 'out'], POINTER(_PinInfo), 'pInfo' )),
    COMMETHOD([], HRESULT, 'QueryDirection',
              ( ['retval', 'out'], POINTER(_PinDirection), 'pPinDir' )),
    COMMETHOD([], HRESULT, 'QueryId',
              ( ['retval', 'out'], POINTER(WSTRING), 'Id' )),
    COMMETHOD([], HRESULT, 'QueryAccept',
              ( ['in'], POINTER(_AMMediaType), 'pmt' )),
    COMMETHOD([], HRESULT, 'EnumMediaTypes',
              ( ['retval', 'out'], POINTER(POINTER(IEnumMediaTypes)), 'ppenum' )),
    COMMETHOD([], HRESULT, 'QueryInternalConnections',
              ( ['out'], POINTER(POINTER(IPin)), 'apPin' ),
              ( ['in', 'out'], POINTER(c_ulong), 'nPin' )),
    COMMETHOD([], HRESULT, 'EndOfStream'),
    COMMETHOD([], HRESULT, 'BeginFlush'),
    COMMETHOD([], HRESULT, 'EndFlush'),
    COMMETHOD([], HRESULT, 'NewSegment',
              ( ['in'], c_longlong, 'tStart' ),
              ( ['in'], c_longlong, 'tStop' ),
              ( ['in'], c_double, 'dRate' )),
]

IGraphBuilder._methods_ = [
    COMMETHOD([], HRESULT, 'Connect',
              ( ['in'], POINTER(IPin), 'ppinOut' ),
              ( ['in'], POINTER(IPin), 'ppinIn' )),
    COMMETHOD([], HRESULT, 'Render',
              ( ['in'], POINTER(IPin), 'ppinOut' )),
    COMMETHOD([], HRESULT, 'RenderFile',
              ( ['in'], WSTRING, 'lpcwstrFile' ),
              ( ['in'], WSTRING, 'lpcwstrPlayList' )),
    COMMETHOD([], HRESULT, 'AddSourceFilter',
              ( ['in'], WSTRING, 'lpcwstrFileName' ),
              ( ['in'], WSTRING, 'lpcwstrFilterName' ),
              ( ['out'], POINTER(POINTER(IBaseFilter)), 'ppFilter' )),
    COMMETHOD([], HRESULT, 'SetLogFile',
              ( ['in'], ULONG_PTR, 'hFile' )),
    COMMETHOD([], HRESULT, 'Abort'),
    COMMETHOD([], HRESULT, 'ShouldOperationContinue'),
]

IFileSinkFilter._methods_ = [
    COMMETHOD([], HRESULT, 'SetFileName',
              ( ['in'], WSTRING, 'pszFileName' ),
              ( ['in'], POINTER(_AMMediaType), 'pmt' )),
    COMMETHOD([], HRESULT, 'GetCurFile',
              ( ['out'], POINTER(WSTRING), 'ppszFileName' ),
              ( ['out'], POINTER(_AMMediaType), 'pmt' )),
]

ICaptureGraphBuilder2._methods_ = [
    COMMETHOD([], HRESULT, 'SetFiltergraph',
              ( ['in'], POINTER(IGraphBuilder), 'pfg' )),
    COMMETHOD([], HRESULT, 'GetFiltergraph',
              ( ['retval', 'out'], POINTER(POINTER(IGraphBuilder)), 'ppfg' )),
    COMMETHOD([], HRESULT, 'SetOutputFileName',
              ( ['in'], POINTER(GUID), 'pType' ),
              ( ['in'], WSTRING, 'lpstrFile' ),
              ( ['out'], POINTER(POINTER(IBaseFilter)), 'ppf' ),
              ( ['out'], POINTER(POINTER(IFileSinkFilter)), 'ppSink' )),
    COMMETHOD([], HRESULT, 'RemoteFindInterface',
              ( ['in'], POINTER(GUID), 'pCategory' ),
              ( ['in'], POINTER(GUID), 'pType' ),
              ( ['in'], POINTER(IBaseFilter), 'pf' ),
              ( ['in'], POINTER(GUID), 'riid' ),
              ( ['out'], POINTER(POINTER(IUnknown)), 'ppint' )),
    COMMETHOD([], HRESULT, 'RenderStream',
              ( ['in'], POINTER(GUID), 'pCategory' ),
              ( ['in'], POINTER(GUID), 'pType' ),
              ( ['in'], POINTER(IUnknown), 'pSource' ),
              ( ['in'], POINTER(IBaseFilter), 'pfCompressor' ),
              ( ['in'], POINTER(IBaseFilter), 'pfRenderer' )),
    COMMETHOD([], HRESULT, 'ControlStream',
              ( ['in'], POINTER(GUID), 'pCategory' ),
              ( ['in'], POINTER(GUID), 'pType' ),
              ( ['in'], POINTER(IBaseFilter), 'pFilter' ),
              ( ['in'], POINTER(c_longlong), 'pstart' ),
              ( ['in'], POINTER(c_longlong), 'pStop' ),
              ( ['in'], c_ushort, 'wStartCookie' ),
              ( ['in'], c_ushort, 'wStopCookie' )),
    COMMETHOD([], HRESULT, 'AllocCapFile',
              ( ['in'], WSTRING, 'lpstr' ),
              ( ['in'], c_ulonglong, 'dwlSize' )),
    COMMETHOD([], HRESULT, 'CopyCaptureFile',
              ( ['in'], WSTRING, 'lpwstrOld' ),
              ( ['in'], WSTRING, 'lpwstrNew' ),
              ( ['in'], c_int, 'fAllowEscAbort' ),
              ( ['in'], POINTER(IAMCopyCaptureFileProgress), 'pCallback' )),
    COMMETHOD([], HRESULT, 'FindPin',
              ( ['in'], POINTER(IUnknown), 'pSource' ),
              ( ['in'], _PinDirection, 'pindir' ),
              ( ['in'], POINTER(GUID), 'pCategory' ),
              ( ['in'], POINTER(GUID), 'pType' ),
              ( ['in'], c_int, 'fUnconnected' ),
              ( ['in'], c_int, 'num' ),
              ( ['out'], POINTER(POINTER(IPin)), 'ppPin' )),
]

IStream._methods_ = [
    COMMETHOD([], HRESULT, 'RemoteSeek',
              ( ['in'], _LARGE_INTEGER, 'dlibMove' ),
              ( ['in'], c_ulong, 'dwOrigin' ),
              ( ['out'], POINTER(_ULARGE_INTEGER), 'plibNewPosition' )),
    COMMETHOD([], HRESULT, 'SetSize',
              ( ['in'], _ULARGE_INTEGER, 'libNewSize' )),
    COMMETHOD([], HRESULT, 'RemoteCopyTo',
              ( ['in'], POINTER(IStream), 'pstm' ),
              ( ['in'], _ULARGE_INTEGER, 'cb' ),
              ( ['out'], POINTER(_ULARGE_INTEGER), 'pcbRead' ),
              ( ['out'], POINTER(_ULARGE_INTEGER), 'pcbWritten' )),
    COMMETHOD([], HRESULT, 'Commit',
              ( ['in'], c_ulong, 'grfCommitFlags' )),
    COMMETHOD([], HRESULT, 'Revert'),
    COMMETHOD([], HRESULT, 'LockRegion',
              ( ['in'], _ULARGE_INTEGER, 'libOffset' ),
              ( ['in'], _ULARGE_INTEGER, 'cb' ),
              ( ['in'], c_ulong, 'dwLockType' )),
    COMMETHOD([], HRESULT, 'UnlockRegion',
              ( ['in'], _ULARGE_INTEGER, 'libOffset' ),
              ( ['in'], _ULARGE_INTEGER, 'cb' ),
              ( ['in'], c_ulong, 'dwLockType' )),
    COMMETHOD([], HRESULT, 'Stat',
              ( ['out'], POINTER(tagSTATSTG), 'pstatstg' ),
              ( ['in'], c_ulong, 'grfStatFlag' )),
    COMMETHOD([], HRESULT, 'Clone',
              ( ['out'], POINTER(POINTER(IStream)), 'ppstm' )),
]

IPersistStream._methods_ = [
    COMMETHOD([], HRESULT, 'IsDirty'),
    COMMETHOD([], HRESULT, 'Load',
              ( ['in'], POINTER(IStream), 'pstm' )),
    COMMETHOD([], HRESULT, 'Save',
              ( ['in'], POINTER(IStream), 'pstm' ),
              ( ['in'], c_int, 'fClearDirty' )),
    COMMETHOD([], HRESULT, 'GetSizeMax',
              ( ['out'], POINTER(_ULARGE_INTEGER), 'pcbSize' )),
]

IMoniker._methods_ = [
    COMMETHOD([], HRESULT, 'RemoteBindToObject',
              ( ['in'], POINTER(IBindCtx), 'pbc' ),
              ( ['in'], POINTER(IMoniker), 'pmkToLeft' ),
              ( ['in'], POINTER(GUID), 'riidResult' ),
              ( ['out'], POINTER(POINTER(IUnknown)), 'ppvResult' )),
    COMMETHOD([], HRESULT, 'RemoteBindToStorage',
              ( ['in'], POINTER(IBindCtx), 'pbc' ),
              ( ['in'], POINTER(IMoniker), 'pmkToLeft' ),
              ( ['in'], POINTER(GUID), 'riid' ),
              ( ['out'], POINTER(POINTER(IUnknown)), 'ppvObj' )),
    COMMETHOD([], HRESULT, 'Reduce',
              ( ['in'], POINTER(IBindCtx), 'pbc' ),
              ( ['in'], c_ulong, 'dwReduceHowFar' ),
              ( ['in', 'out'], POINTER(POINTER(IMoniker)), 'ppmkToLeft' ),
              ( ['out'], POINTER(POINTER(IMoniker)), 'ppmkReduced' )),
    COMMETHOD([], HRESULT, 'ComposeWith',
              ( ['in'], POINTER(IMoniker), 'pmkRight' ),
              ( ['in'], c_int, 'fOnlyIfNotGeneric' ),
              ( ['out'], POINTER(POINTER(IMoniker)), 'ppmkComposite' )),
    COMMETHOD([], HRESULT, 'Enum',
              ( ['in'], c_int, 'fForward' ),
              ( ['out'], POINTER(POINTER(IEnumMoniker)), 'ppenumMoniker' )),
    COMMETHOD([], HRESULT, 'IsEqual',
              ( ['in'], POINTER(IMoniker), 'pmkOtherMoniker' )),
    COMMETHOD([], HRESULT, 'Hash',
              ( ['out'], POINTER(c_ulong), 'pdwHash' )),
    COMMETHOD([], HRESULT, 'IsRunning',
              ( ['in'], POINTER(IBindCtx), 'pbc' ),
              ( ['in'], POINTER(IMoniker), 'pmkToLeft' ),
              ( ['in'], POINTER(IMoniker), 'pmkNewlyRunning' )),
    COMMETHOD([], HRESULT, 'GetTimeOfLastChange',
              ( ['in'], POINTER(IBindCtx), 'pbc' ),
              ( ['in'], POINTER(IMoniker), 'pmkToLeft' ),
              ( ['out'], POINTER(_FILETIME), 'pfiletime' )),
    COMMETHOD([], HRESULT, 'Inverse',
              ( ['out'], POINTER(POINTER(IMoniker)), 'ppmk' )),
    COMMETHOD([], HRESULT, 'CommonPrefixWith',
              ( ['in'], POINTER(IMoniker), 'pmkOther' ),
              ( ['out'], POINTER(POINTER(IMoniker)), 'ppmkPrefix' )),
    COMMETHOD([], HRESULT, 'RelativePathTo',
              ( ['in'], POINTER(IMoniker), 'pmkOther' ),
              ( ['out'], POINTER(POINTER(IMoniker)), 'ppmkRelPath' )),
    COMMETHOD([], HRESULT, 'GetDisplayName',
              ( ['in'], POINTER(IBindCtx), 'pbc' ),
              ( ['in'], POINTER(IMoniker), 'pmkToLeft' ),
              ( ['out'], POINTER(WSTRING), 'ppszDisplayName' )),
    COMMETHOD([], HRESULT, 'ParseDisplayName',
              ( ['in'], POINTER(IBindCtx), 'pbc' ),
              ( ['in'], POINTER(IMoniker), 'pmkToLeft' ),
              ( ['in'], WSTRING, 'pszDisplayName' ),
              ( ['out'], POINTER(c_ulong), 'pchEaten' ),
              ( ['out'], POINTER(POINTER(IMoniker)), 'ppmkOut' )),
    COMMETHOD([], HRESULT, 'IsSystemMoniker',
              ( ['out'], POINTER(c_ulong), 'pdwMksys' )),
]

IBindCtx._methods_ = [
    COMMETHOD([], HRESULT, 'RegisterObjectBound',
              ( ['in'], POINTER(IUnknown), 'punk' )),
    COMMETHOD([], HRESULT, 'RevokeObjectBound',
              ( ['in'], POINTER(IUnknown), 'punk' )),
    COMMETHOD([], HRESULT, 'ReleaseBoundObjects'),
    COMMETHOD([], HRESULT, 'RemoteSetBindOptions',
              ( ['in'], POINTER(tagBIND_OPTS2), 'pbindopts' )),
    COMMETHOD([], HRESULT, 'RemoteGetBindOptions',
              ( ['in', 'out'], POINTER(tagBIND_OPTS2), 'pbindopts' )),
    COMMETHOD([], HRESULT, 'GetRunningObjectTable',
              ( ['out'], POINTER(POINTER(IRunningObjectTable)), 'pprot' )),
    COMMETHOD([], HRESULT, 'RegisterObjectParam',
              ( ['in'], WSTRING, 'pszKey' ),
              ( ['in'], POINTER(IUnknown), 'punk' )),
    COMMETHOD([], HRESULT, 'GetObjectParam',
              ( ['in'], WSTRING, 'pszKey' ),
              ( ['out'], POINTER(POINTER(IUnknown)), 'ppunk' )),
    COMMETHOD([], HRESULT, 'EnumObjectParam',
              ( ['out'], POINTER(POINTER(IEnumString)), 'ppenum' )),
    COMMETHOD([], HRESULT, 'RevokeObjectParam',
              ( ['in'], WSTRING, 'pszKey' )),
]

IEnumMoniker._methods_ = [
    COMMETHOD([], HRESULT, 'RemoteNext',
              ( ['in'], c_ulong, 'celt' ),
              ( ['out'], POINTER(POINTER(IMoniker)), 'rgelt' ),
              ( ['out'], POINTER(c_ulong), 'pceltFetched' )),
    COMMETHOD([], HRESULT, 'Skip',
              ( ['in'], c_ulong, 'celt' )),
    COMMETHOD([], HRESULT, 'Reset'),
    COMMETHOD([], HRESULT, 'Clone',
              ( ['out'], POINTER(POINTER(IEnumMoniker)), 'ppenum' )),
]

IRunningObjectTable._methods_ = [
    COMMETHOD([], HRESULT, 'Register',
              ( ['in'], c_ulong, 'grfFlags' ),
              ( ['in'], POINTER(IUnknown), 'punkObject' ),
              ( ['in'], POINTER(IMoniker), 'pmkObjectName' ),
              ( ['out'], POINTER(c_ulong), 'pdwRegister' )),
    COMMETHOD([], HRESULT, 'Revoke',
              ( ['in'], c_ulong, 'dwRegister' )),
    COMMETHOD([], HRESULT, 'IsRunning',
              ( ['in'], POINTER(IMoniker), 'pmkObjectName' )),
    COMMETHOD([], HRESULT, 'GetObject',
              ( ['in'], POINTER(IMoniker), 'pmkObjectName' ),
              ( ['out'], POINTER(POINTER(IUnknown)), 'ppunkObject' )),
    COMMETHOD([], HRESULT, 'NoteChangeTime',
              ( ['in'], c_ulong, 'dwRegister' ),
              ( ['in'], POINTER(_FILETIME), 'pfiletime' )),
    COMMETHOD([], HRESULT, 'GetTimeOfLastChange',
              ( ['in'], POINTER(IMoniker), 'pmkObjectName' ),
              ( ['out'], POINTER(_FILETIME), 'pfiletime' )),
    COMMETHOD([], HRESULT, 'EnumRunning',
              ( ['out'], POINTER(POINTER(IEnumMoniker)), 'ppenumMoniker' )),
]

IEnumString._methods_ = [
    COMMETHOD([], HRESULT, 'RemoteNext',
              ( ['in'], c_ulong, 'celt' ),
              ( ['out'], POINTER(WSTRING), 'rgelt' ),
              ( ['out'], POINTER(c_ulong), 'pceltFetched' )),
    COMMETHOD([], HRESULT, 'Skip',
              ( ['in'], c_ulong, 'celt' )),
    COMMETHOD([], HRESULT, 'Reset'),
    COMMETHOD([], HRESULT, 'Clone',
              ( ['out'], POINTER(POINTER(IEnumString)), 'ppenum' )),
]

ICreateDevEnum._methods_ = [
    COMMETHOD([], HRESULT, 'CreateClassEnumerator',
              ( ['in'], POINTER(GUID), 'clsidDeviceClass' ),
              ( ['out'], POINTER(POINTER(IEnumMoniker)), 'ppenumMoniker' ),
              ( ['in'], c_ulong, 'dwFlags' )),
]

IAMCrossbar._methods_ = [
    COMMETHOD([], HRESULT, 'get_PinCounts',
              ( ['out'], POINTER(c_int), 'OutputPinCount' ),
              ( ['out'], POINTER(c_int), 'InputPinCount' )),
    COMMETHOD([], HRESULT, 'CanRoute',
              ( ['in'], c_int, 'OutputPinIndex' ),
              ( ['in'], c_int, 'InputPinIndex' )),
    COMMETHOD([], HRESULT, 'Route',
              ( ['in'], c_int, 'OutputPinIndex' ),
              ( ['in'], c_int, 'InputPinIndex' )),
    COMMETHOD([], HRESULT, 'get_IsRoutedTo',
              ( ['in'], c_int, 'OutputPinIndex' ),
              ( ['out'], POINTER(c_int), 'InputPinIndex' )),
    COMMETHOD([], HRESULT, 'get_CrossbarPinInfo',
              ( ['in'], c_int, 'IsInputPin' ),
              ( ['in'], c_int, 'PinIndex' ),
              ( ['out'], POINTER(c_int), 'PinIndexRelated' ),
              ( ['out'], POINTER(c_int), 'PhysicalType' )),
]

IEnumPins._methods_ = [
    COMMETHOD([], HRESULT, 'Next',
              ( ['in'], c_ulong, 'cPins' ),
              ( ['out'], POINTER(POINTER(IPin)), 'ppPins' ),
              ( ['out'], POINTER(c_ulong), 'pcFetched' )),
    COMMETHOD([], HRESULT, 'Skip',
              ( ['in'], c_ulong, 'cPins' )),
    COMMETHOD([], HRESULT, 'Reset'),
    COMMETHOD([], HRESULT, 'Clone',
              ( ['retval', 'out'], POINTER(POINTER(IEnumPins)), 'ppenum' )),
]

IAMAnalogVideoDecoder._methods_ = [
    COMMETHOD([], HRESULT, 'get_AvailableTVFormats',
              ( ['out'], POINTER(c_int), 'lAnalogVideoStandard' )),
    COMMETHOD([], HRESULT, 'put_TVFormat',
              ( ['in'], c_int, 'lAnalogVideoStandard' )),
    COMMETHOD([], HRESULT, 'get_TVFormat',
              ( ['out'], POINTER(c_int), 'plAnalogVideoStandard' )),
    COMMETHOD([], HRESULT, 'get_HorizontalLocked',
              ( ['out'], POINTER(c_int), 'plLocked' )),
    COMMETHOD([], HRESULT, 'put_VCRHorizontalLocking',
              ( ['in'], c_int, 'lVCRHorizontalLocking' )),
    COMMETHOD([], HRESULT, 'get_VCRHorizontalLocking',
              ( ['out'], POINTER(c_int), 'plVCRHorizontalLocking' )),
    COMMETHOD([], HRESULT, 'get_NumberOfLines',
              ( ['out'], POINTER(c_int), 'plNumberOfLines' )),
    COMMETHOD([], HRESULT, 'put_OutputEnable',
              ( ['in'], c_int, 'lOutputEnable' )),
    COMMETHOD([], HRESULT, 'get_OutputEnable',
              ( ['out'], POINTER(c_int), 'plOutputEnable' )),
]
